"""
Case Type   : 非默认端口下系统内部使用工具 gs_sshexkey
Case Name   : 非默认端口，普通用户下，使用gs_sshexkey对一主一备创建互信
Create At   : 2025/5/12
Owner       : l1azzzy
Description :
    1、创建hostfile,文件路径{dn1/hostfile},将环境IP写入文件hostfile
       touch {dn1/hostfile}
       chmod -R 755 {dn1/hostfile}
       echo -e '{IP1\nIP2}' {dn1/hostfile}
    2、普通用户下，执行gs_sshexkey -f {dn1/hostfile} -W {db_password}
    3、ssh添加的备机IP
    4、查看互信文件是否存在
    5、清理环境、删除互信文件
Expect      :
    1、创建文件成功，添加IP成功
    2、执行gs_sshexkey命令成功
    3、ssh可直接连接到备机，互信建立成功
    4、互信文件存在
    5、清理环境成功
History     :
"""

import os
import unittest
from yat.test import Node
from yat.test import macro
from testcase.utils.Logger import Logger
from testcase.utils.CommonSH import CommonSH

logger = Logger()
primary_sh = CommonSH('PrimaryDbUser')


@unittest.skipIf(1 == primary_sh.get_node_num(),
                 'Single node, and subsequent codes are not executed.')
class ToolsTestCase(unittest.TestCase):
    def setUp(self):
        self.commonsh = CommonSH('PrimaryDbUser')
        self.primary_root_node = Node('PrimaryRoot')
        self.primary_node = Node('PrimaryDbUser')
        self.standby_node = Node('Standby1DbUser')
        self.IP2 = self.standby_node.db_host
        self.IP1 = self.primary_node.db_host
        self.ssh_file = os.path.join('/home',
                                     self.primary_node.ssh_user,
                                     'hostfile')
        self.conf_path = os.path.join(macro.DB_INSTANCE_PATH,
                                      macro.DB_PG_CONFIG_NAME)
        logger.info("======SetUp：检查数据库状态是否正常======")
        status = self.commonsh.get_db_cluster_status()
        self.assertTrue("Degraded" in status or "Normal" in status)
        logger.info("======获取备节点ip======")
        shell_cmd = f"cat {self.conf_path} | " \
            f"grep 'replconninfo' | " \
            f"grep -Ev '^#' | " \
            f"tr -s ' '| " \
            f"cut -d ' ' -f 7 | " \
            f"cut -d '=' -f 2"
        logger.info(shell_cmd)
        msg = self.primary_node.sh(shell_cmd).result()
        logger.info(msg)
        self.standby_ip_list = msg.splitlines()
        self.encrypt_file = os.path.join(macro.DB_SCRIPT_PATH, 'gspylib/clib/encrypt')
        text = '-----修改SSH端口 expect:成功-----'
        self.log.info(text)
        self.log.info('----备份SSH配置文件----')
        res = self.pri_node_root.sh(f'cp /etc/sshd_config /etc/sshd_config.bak')
        self.log.info('----修改SSH端口----')
        res = self.pri_node_root.sh(f"sed -i '/^#*Port /s/^#*Port .*/Port 2222/' /etc/ssh/sshd_config")
        self.log.info(res)
        self.log.info('----重启SSH服务----')
        res = self.pri_node_root.sh(f"systemctl restart sshd")
        self.log.info(res)
        self.log.info('----查看SSH端口是否修改成功----')
        res = self.pri_node_root.sh(f"ss -tnlp | grep 2222")
        self.log.info(res)
        self.assertIn('2222', res, 'SSH端口修改失败')

    def test_gs_sshexkey(self):
        logger.info(f"====={os.path.basename(__file__)}开始执行=====")
        logger.info("======步驟1：普通用户下创建hostfile文件，添加主备IP信息======")
        add_cmd1 = f'''touch {self.ssh_file}
                       echo -e '{self.IP1}' > {self.ssh_file}
                       cat {self.ssh_file} | grep {self.IP1}'''
        logger.info(add_cmd1)
        add_res1 = self.primary_node.sh(add_cmd1).result()
        self.assertTrue(self.IP1 in add_res1)

        for i in self.standby_ip_list:
            add_cmd2 = f'''echo -e '{i}' >> {self.ssh_file}
                        cat {self.ssh_file}'''
            logger.info(add_cmd2)
            add_res2 = self.primary_node.sh(add_cmd2).result()
            logger.info(add_res2)
            self.assertTrue(i in add_res2)

        logger.info("======步驟2：执行gs_sshexkey命令======")
        gs_cmd = f'''gs_sshexkey -f {self.ssh_file}'''
        execute_cmd = f'''source {macro.DB_ENV_PATH}
            expect <<EOF
            set timeout 300
            spawn {gs_cmd}
            expect "*assword:"
            send "{self.primary_node.ssh_password}\\n"
            expect eof\n''' + '''EOF'''
        logger.info(execute_cmd)
        gs_res = self.primary_node.sh(execute_cmd).result()
        logger.info(gs_res)
        self.assertIn('Successfully created SSH trust', gs_res)

        logger.info("======步驟3：ssh连接备机，无需密码可正常连接======")
        text = '----修改encrypt文件权限----'
        logger.info(text)
        cmd = f"chown {self.primary_node.ssh_user}:{self.primary_node.ssh_user} {self.encrypt_file};"
        logger.info(cmd)
        res = self.primary_root_node.sh(cmd).result()
        self.assertEqual('', res, f"执行失败:{text}")

        ssh_cmd = f'''ssh {self.IP2} <<-EOF hostname\n''' + "EOF"
        logger.info(ssh_cmd)
        ssh_res = self.primary_node.sh(ssh_cmd).result()
        logger.info(ssh_res)
        standby_hostname = self.standby_node.sh('hostname').result()
        self.assertEqual(standby_hostname, ssh_res.split('\n')[-1])

        logger.info("======步驟4：查看互信文件是否存在======")
        check_cmd = 'cd ~/.ssh;ls'
        self.check_res = self.primary_node.sh(check_cmd).result()
        logger.info(self.check_res)
        self.assertTrue(self.check_res)

    def tearDown(self):
        logger.info("======步驟5：清理环境，删除hostfile文件======")
        rm_cmd1 = f'''rm -rf {self.ssh_file}'''
        logger.info(rm_cmd1)
        rm_res1 = self.primary_node.sh(rm_cmd1).result()
        rm_res2 = self.standby_node.sh(rm_cmd1).result()
        self.assertNotIn('bash', rm_res1)
        self.assertNotIn('bash', rm_res2)
        logger.info(f"====={os.path.basename(__file__)}执行结束=====")
